home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
asmutil
/
68kdis.zip
/
ROBJ.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-12-03
|
18KB
|
859 lines
/*
* SCCS: @(#)robj.c 1.2 11/2/84 14:19:59
* Read object files.
*
***********************************************************************
* This software is copyright of
*
* John M Collins
* 47 Cedarwood Drive
* St Albans
* Herts, AL4 0DN
* England +44 727 57267
*
* and is released into the public domain on the following conditions:
*
* 1. No free maintenance will be guaranteed.
* 2. Nothing may be based on this software without
* acknowledgement, including incorporation of this
* notice.
*
* Notwithstanding the above, the author welcomes correspondence and bug
* fixes.
***********************************************************************
*
* This particular module will obviously have to be munged beyond
* recognition for another object format.
*/
#include <stdio.h>
#include <a.out.h>
#include <ldfcn.h>
#include <string.h>
#include "unc.h"
void gette(), getde(), setde(), putte(), putde();
long gettw(), getdw();
void reallst(), lclash(), nomem(), unimpl();
void addit();
char *malloc();
long lseek();
int par_entry, par_round, nmods, donedrel, donebrel;
struct commit abstab, comtab, dreltab;
long trelpos, drelpos, brelpos;
int *symord; /* convert symbol index to symbol ordinal */
ef_fids mainfile;
symbol lookup(), inventsymb(), getnsymb();
#define RWORD 1
#define RLONG 2
#define DBSIZE 100
#define STINIT 20
/*
* Read text segment. Return 0 if not ok.
*/
int rtext(ldptr, outf)
LDFILE *ldptr; /* a.out file (possibly in library) */
ef_fid outf; /* Output file descriptor */
{
t_entry tstr;
struct aouthdr unixhdr;
struct scnhdr sect;
register long size;
register int i, l;
unsigned short inbuf[DBSIZE/2];
/*
* Initialise fields in structure.
*/
tstr.t_type = T_UNKNOWN;
tstr.t_vins = 1; /* For the moment */
tstr.t_bdest = 0;
tstr.t_gbdest = 0;
tstr.t_lng = 1;
tstr.t_reloc = R_NONE;
tstr.t_rdisp = 0;
tstr.t_isrel = 0;
tstr.t_amap = 0;
tstr.t_dref = 0;
tstr.t_relsymb = NULL;
tstr.t_reldisp = 0;
tstr.t_lab = NULL;
tstr.t_lsymb = 0;
tstr.t_refhi = 0;
tstr.t_reflo = 0x7fffffff;
tstr.t_match = 0;
/*
* Read a.out header.
*/
if (ldohseek(ldptr) == FAILURE) { /* no optional header */
outf->ef_entry = 0;
ldshread(ldptr,1,§); /* text header */
outf->ef_tbase = sect.s_vaddr;
outf->ef_tsize = sect.s_size;
ldshread(ldptr,2,§); /* data header */
outf->ef_dbase = sect.s_vaddr;
outf->ef_dsize = sect.s_size;
ldshread(ldptr,3,§); /* bss header */
outf->ef_bbase = sect.s_vaddr;
outf->ef_bsize = sect.s_size;
outf->ef_end = sect.s_vaddr + sect.s_size;
} else {
FREAD((char *)&unixhdr,sizeof(struct aouthdr),1,ldptr);
if ( N_BADMAG(unixhdr) )
return 0;
outf->ef_entry = unixhdr.entry;
outf->ef_tbase = unixhdr.text_start;
outf->ef_dbase = unixhdr.data_start;
outf->ef_bbase = outf->ef_dbase + unixhdr.dsize;
outf->ef_end = outf->ef_bbase + unixhdr.bsize;
outf->ef_tsize = unixhdr.tsize;
outf->ef_dsize = unixhdr.dsize;
outf->ef_bsize = unixhdr.bsize;
}
ldsseek(ldptr,1); /* seek to text section */
size = outf->ef_tsize;
while (size > 1) {
l = size > DBSIZE? DBSIZE: size;
if (FREAD((char *)inbuf,1,l,ldptr) != l)
return 0;
l /= 2;
for (i = 0; i < l; i++) {
tstr.t_contents = inbuf[i];
(void) write(outf->ef_t, (char *)&tstr, sizeof(tstr));
}
size -= l + l;
}
/*
* Extra one to cope with "etext".
*/
(void) write(outf->ef_t, (char *)&tstr, sizeof(tstr));
return 1;
}
/*
* Same sort of thing for the data segment.
*/
int rdata(ldptr, outf)
LDFILE *ldptr; /* a.out file (possibly in library) */
ef_fid outf; /* Output file descriptor */
{
d_entry dstr;
register long size;
register int i, l;
unsigned char inbuf[DBSIZE];
/*
* Initialise fields in structure.
*/
dstr.d_type = D_BYTE;
dstr.d_reloc = R_NONE;
dstr.d_lng = 1;
dstr.d_relsymb = NULL;
dstr.d_reldisp = 0;
dstr.d_lab = NULL;
ldsseek(ldptr,2); /* seek to data section */
size = outf->ef_dsize;
while (size > 0) {
l = size > DBSIZE? DBSIZE: size;
if (FREAD((char *)inbuf,1,l,ldptr) != l)
return 0;
for (i = 0; i < l; i++) {
dstr.d_contents = inbuf[i];
(void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
}
size -= l;
}
/*
* Repeat for BSS segment.
*/
dstr.d_contents = 0;
for (size = outf->ef_bsize; size > 0; size--)
(void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
/*
* Extra one to cope with "end".
*/
(void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
return 1;
}
/*
* Process symbol table segment.
*/
int rsymb(ldptr, dproc, outf)
LDFILE *ldptr; /* a.out file (possibly in library) */
symbol (*dproc)();
register ef_fid outf; /* Output file descriptor */
{
#define SYMLENGTH 256
register symbol csym;
struct syment isym;
register int nsyms,symindex;
unsigned long stroff;
char inbuf[SYMLENGTH+1], *cp;
int ord;
nsyms = HEADER(ldptr).f_nsyms;
stroff = HEADER(ldptr).f_symptr + nsyms*sizeof(struct syment);
if (nsyms <= 0)
nsyms = STINIT;
outf->ef_stvec = (symbol *) malloc(nsyms * sizeof(symbol));
symord = (int *) malloc(nsyms * sizeof(int));
if (outf->ef_stvec == NULL)
nomem();
outf->ef_stcnt = 0;
outf->ef_stmax = nsyms;
ord = 0;
for (symindex=0; symindex<nsyms; symindex++) {
ldtbread(ldptr,symindex,&isym);
if (isym.n_zeroes == 0) { /* get from string table */
FSEEK(ldptr,stroff + isym.n_offset,0);
cp = inbuf;
do {
if (FREAD(cp,1,1,ldptr) != 1)/* Read symbol chars 1-by-1 */
return 0;
if ( cp - inbuf >= SYMLENGTH )/* Check against buffer overflow */
return 0;
} while (*cp++ != '\0');/* Terminate on null byte */
} else { /* get from symbol field */
strncpy(inbuf,isym.n_name,8);
inbuf[8] = '\0';
}
csym = (*dproc)(lookup(inbuf), convtosun(&isym),
isym.n_value, outf);
if (outf->ef_stcnt >= outf->ef_stmax)
reallst(outf);
outf->ef_stvec[outf->ef_stcnt++] = csym;
symord[symindex] = ord++; /* record ordinal */
symindex += isym.n_numaux; /* skip aux entries */
}
return 1;
}
/*
* Process relocation stuff. -1 error, 0 no relocation, 1 relocation.
*/
int rrel(ldptr, ldptr2, outf)
LDFILE *ldptr,*ldptr2; /* a.out file (possibly in library) */
ef_fid outf; /* Output file descriptor */
{
struct reloc crel;
struct scnhdr tsect,dsect;
struct syment isym;
t_entry tstr;
d_entry dstr;
register int nreloc;
long cont, pos;
ldshread(ldptr,1,&tsect);
ldshread(ldptr,2,&dsect);
if (tsect.s_nreloc <= 0 && dsect.s_nreloc <= 0)
return 0;
nreloc = tsect.s_nreloc;
ldrseek(ldptr,1);
while (nreloc-- > 0) {
if (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1)
return -1;
pos = crel.r_vaddr;
gette(outf, pos, &tstr);
if (crel.r_type == R_ABS)
tstr.t_reloc = R_NONE;
else
tstr.t_reloc = R_LONG; /* what about PC-relative? */
ldtbread(ldptr2,crel.r_symndx,&isym);
if (isym.n_sclass == C_EXT) {
tstr.t_relsymb = outf->ef_stvec[symord[crel.r_symndx]];
tstr.t_reldisp = gettw(outf, pos, (int)tstr.t_reloc);
}
else {
cont = gettw(outf, pos, (int)tstr.t_reloc);
tstr.t_relsymb = getnsymb(outf, convtosun(&isym), cont);
}
tstr.t_relsymb->s_used++;
putte(outf, pos, &tstr);
}
/*
* And now repeat all that for data relocations.
*/
nreloc = dsect.s_nreloc;
ldrseek(ldptr,2);
while (nreloc-- > 0) {
if (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1)
return -1;
pos = crel.r_vaddr;
getde(outf, pos, &dstr);
if (crel.r_type == R_ABS)
dstr.d_reloc = R_NONE;
else
dstr.d_reloc = R_LONG; /* what about PC-relative? */
ldtbread(ldptr2,crel.r_symndx,&isym);
if (isym.n_sclass == C_EXT) {
dstr.d_relsymb = outf->ef_stvec[symord[crel.r_symndx]];
dstr.d_reldisp = getdw(outf, pos, (int)dstr.d_reloc);
}
else {
cont = getdw(outf, pos, (int)dstr.d_reloc);
dstr.d_relsymb = getnsymb(outf, convtosun(&isym), cont);
if (dstr.d_relsymb->s_type == S_TEXT) {
gette(outf, cont, &tstr);
tstr.t_